﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using ActivateYourGlutes.Controllers;
using ActivateYourGlutes.Data;
using ActivateYourGlutes.Infrastructure;
using ActivateYourGlutes.Services.Model;
using NUnit.Framework;
using Rhino.Mocks;

namespace ActivateYourGlutes.Tests.Unit.Controllers
{
    [TestFixture]
    public class Test_AdministerUsersController : ControllerTestBase
    {
        private AdministerUsersController _administerUsersController;
        private IEnumerable<Account> _accounts;

        public override void Init()
        {
            base.Init();
            _administerUsersController = new AdministerUsersController(_commonAccountProvider, _logger);
            _administerUsersController.ControllerContext = new ControllerContext(_httpContext, new RouteData(), _administerUsersController);
            _administerUsersController.LocaleSettings = _localeSettings;
            _accounts = new List<Account>()
                            {
                                _mockAccount,
                                new Account()
                                    {
                                        AccountId = 1,
                                        DateOfBirth = new DateTime(1992, 2, 3),
                                        LocalDateFormat = "dd-MM-yyyy",
                                        PrimaryMeasurementType = _weight,
                                        SecondaryMeasurementType = _bodyFat,
                                        UnitOfLength = _centimeters,
                                        UnitOfWeight = _kilogrammes
                                    }
                            };
        }

        [Test]
        public void Test_Index_Get_ReturnsView()
        {
            // Act
            ViewResult result = (ViewResult)_administerUsersController.Index();
        }

        [Test]
        public void Test_GridData_Get_ReturnsJson()
        {
            // Arrange
            _commonAccountProvider.Stub(ap => ap.TotalAccounts(null)).IgnoreArguments().Return(_accounts.Count());
            _commonAccountProvider.Stub(ep => ep.Accounts(null, 1, 10)).IgnoreArguments().Return(_accounts);

            // Act
            JsonResult result = (JsonResult)_administerUsersController.GridData("Date", "Date", 1, 10);

            // Assert
            Assert.That(result.Data, Is.Not.Null);
        }

        [Test]
        public void Test_Edit_Get_ReturnsView()
        {
            // Arrange
            _commonAccountProvider.Stub(ap => ap.GetAccount(null, 1)).IgnoreArguments().Return(_mockAccount);

            // Act
            ViewResult result = (ViewResult) _administerUsersController.Edit(1);

            // Assert
            Assert.That(result.ViewData.Model, Is.EqualTo(_mockAccount));
        }

        [Test]
        public void Test_Edit_Get_UnauthorizedRedirects()
        {
            // Arrange
            _commonAccountProvider.Stub(ap => ap.GetAccount(null, 1)).IgnoreArguments().Throw(
                new AuthorizationException());

            // Act
            RedirectToRouteResult result = (RedirectToRouteResult) _administerUsersController.Edit(1);

            // Assert
            AssertRedirectToUnauthorized(result);
        }

        [Test]
        public void Test_Edit_Post_RedirectsToIndex()
        {
            // Act
            RedirectToRouteResult result = (RedirectToRouteResult) _administerUsersController.Edit(1, true);

            // Assert
            Assert.That(result.RouteValues["controller"], Is.EqualTo("AdministerUsers"));
            Assert.That(result.RouteValues["action"], Is.EqualTo("Index"));
        }

        [Test]
        public void Test_Edit_Post_ValidationError()
        {
            // Arrange
            _commonAccountProvider.Stub(ap => ap.AdminUpdateAccount(null, 1, true)).IgnoreArguments().Throw(
                new ValidationException("error", "description"));

            // Act
            ViewResult result = (ViewResult) _administerUsersController.Edit(1, true);

            // Assert
            Assert.That(result.ViewData.ModelState["error"].Errors[0].ErrorMessage,
                        Is.EqualTo("description"));
        }

        [Test]
        public void Test_Edit_Post_RedirectsOnUnauthorized()
        {
            // Arrange
            _commonAccountProvider.Stub(ap => ap.AdminUpdateAccount(null, 1, true)).IgnoreArguments().Throw(
                new AuthorizationException());

            // Act
            RedirectToRouteResult result = (RedirectToRouteResult) _administerUsersController.Edit(1, true);

            // Assert
            AssertRedirectToUnauthorized(result);
        }

        [Test]
        public void Test_Delete_AjaxDelete_ReturnsTrue()
        {
            // Arrange
            int accountId = _mockAccount.AccountId + 1; // ensure we don't try and delete ourselves
            _commonAccountProvider.Expect(ap => ap.Delete(null, accountId)).IgnoreArguments();
            _httpContext.IsAjaxRequest = true;

            // Act
            JsonResult result = (JsonResult)_administerUsersController.Delete(accountId);

            // Assert
            Assert.That(result.Data, Is.True);
            _commonAccountProvider.VerifyAllExpectations();
        }

        [Test]
        public void Test_Delete_AjaxDelete_ReturnsFalseOnUnauthorised()
        {
            // Arrange
            int accountId = _mockAccount.AccountId + 1; // ensure we don't try and delete ourselves
            _commonAccountProvider.Stub(bp => bp.Delete(null, accountId)).IgnoreArguments().Throw(new AuthorizationException());
            _httpContext.IsAjaxRequest = true;

            // Act
            JsonResult result = (JsonResult)_administerUsersController.Delete(accountId);

            // Assert
            Assert.That(result.Data, Is.False);
        }

        [Test]
        public void Test_Delete_AjaxDelete_ReturnsFalseOnSelfDelete()
        {
            // Arrange
            _commonAccountProvider.Stub(bp => bp.Delete(null, _mockAccount.AccountId)).IgnoreArguments().Throw(new AuthorizationException());
            _httpContext.IsAjaxRequest = true;

            // Act
            JsonResult result = (JsonResult)_administerUsersController.Delete(_mockAccount.AccountId);

            // Assert
            Assert.That(result.Data, Is.False);
        }
    }
}
